// 获取 user 管理页面视图
void Request_View_Auth_User(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 登录页面
		LoadPage(c, 200, HTTP_CT_HTML, "auth/user.html");
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// 获取 role 管理页面视图
void Request_View_Auth_Role(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 登录页面
		LoadPage(c, 200, HTTP_CT_HTML, "auth/role.html");
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// 获取 group 管理页面视图
void Request_View_Auth_Group(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 登录页面
		LoadPage(c, 200, HTTP_CT_HTML, "auth/group.html");
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// 获取 auth 管理页面视图
void Request_View_Auth_Auth(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 登录页面
		LoadPage(c, 200, HTTP_CT_HTML, "auth/auth.html");
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// 获取 uris 管理页面视图
void Request_View_Auth_URIs(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 登录页面
		LoadPage(c, 200, HTTP_CT_HTML, "auth/uris.html");
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}

// 获取 uris 编辑页面视图
void Request_View_Auth_URIs_Edit(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 登录页面
		size_t iSize = 0;
		str sPage = MakePageWithTemplate("auth/uris_edit.html", G_CACHE_Auth_ComboList, &iSize);
		http_reply(c, 200, HTTP_CT_HTML, sPage, iSize);
		xrtFree(sPage);
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// user 主接口
void Request_Auth_User(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 从数据库读取数据
		XDO_Recordset rs = xdoSelect(G_DB, "SELECT * FROM user WHERE isDelete = 0 ORDER BY id ASC;");
		xvalue data = xvoCreateArray();
		while ( xrsNext(rs) ) {
			xvalue tblRow = xvoCreateTable();
			int64 id = xrtStrToI64(xrsGetValue(rs, 0));
			xvoTableSetInt(tblRow, "id", 2, id);
			xvoTableSetInt(tblRow, "role", 4, xrtStrToI64(xrsGetValue(rs, 1)));
			xvoTableSetText(tblRow, "user", 4, xrsGetValue(rs, 2), 0, FALSE);
			// 不返回密码字段
			xtime iTime = xrtStrToI64(xrsGetValue(rs, 4));
			xvoTableSetText(tblRow, "createTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			iTime = xrtStrToI64(xrsGetValue(rs, 5));
			xvoTableSetText(tblRow, "updateTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			xvoArrayAppendValue(data, tblRow, TRUE);
		}
		xrsFree(rs);
		// 返回接口数据
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "用户数据获取成功！", 0, FALSE);
		xvoTableSetValue(tblRet, "data", 4, data, TRUE);
		// 生成 JSON
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_POST ) {
		
		// 添加用户
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 role = xvoTableGetInt(tblForm, "role", 4);
		str user = xvoTableGetText(tblForm, "user", 4);
		str password = xvoTableGetText(tblForm, "password", 8);
		
		// 检查用户名是否已存在
		str sSQL = xrtFormat("SELECT COUNT(*) FROM user WHERE user = '%s' AND isDelete = 0", user);
		XDO_Recordset rs = xdoSelect(G_DB, sSQL);
		xrtFree(sSQL);
		int64 count = 0;
		if (xrsNext(rs)) {
			count = xrtStrToI64(xrsGetValue(rs, 0));
		}
		xrsFree(rs);
		
		if (count > 0) {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"用户名已存在！\"}", 0);
			xvoUnref(tblForm);
			return;
		}
		
		// 计算密码的 MD5 值
		mg_md5_ctx ctx;
		mg_md5_init(&ctx);
		mg_md5_update(&ctx, user, strlen(user));
		mg_md5_update(&ctx, "_xPanel_", 8);
		mg_md5_update(&ctx, password, strlen(password));
		uint8 buf[16];
		mg_md5_final(&ctx, buf);
		str sPwdMD5 = xrtHexEncode(buf, 16);
		
		xtime now = xrtNow();
		
		sqlite3_bind_int64(stmt_user_add, 1, role);
		sqlite3_bind_text(stmt_user_add, 2, user, strlen(user), SQLITE_STATIC);
		sqlite3_bind_text(stmt_user_add, 3, sPwdMD5, strlen(sPwdMD5), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_user_add, 4, now);
		sqlite3_bind_int64(stmt_user_add, 5, now);
		sqlite3_step(stmt_user_add);
		int64 newId = sqlite3_last_insert_rowid(G_DB->objDB);
		sqlite3_reset(stmt_user_add);
		xrtFree(sPwdMD5);
		xvoUnref(tblForm);
		
		// 返回成功信息和新创建的ID
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "用户添加成功！", 0, FALSE);
		xvalue dataRet = xvoCreateTable();
		xvoTableSetInt(dataRet, "id", 2, newId);
		xvoTableSetValue(tblRet, "data", 4, dataRet, TRUE);
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_PUT ) {
		
		// 更新用户
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 id = xvoTableGetInt(tblForm, "id", 2);
		int64 role = xvoTableGetInt(tblForm, "role", 4);
		str user = xvoTableGetText(tblForm, "user", 4);
		
		// 检查用户名是否与其他用户冲突
		str sSQL = xrtFormat("SELECT COUNT(*) FROM user WHERE user = '%s' AND id != %lld AND isDelete = 0", user, id);
		XDO_Recordset rs = xdoSelect(G_DB, sSQL);
		xrtFree(sSQL);
		int64 count = 0;
		if (xrsNext(rs)) {
			count = xrtStrToI64(xrsGetValue(rs, 0));
		}
		xrsFree(rs);
		
		if (count > 0) {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"用户名已存在！\"}", 0);
			xvoUnref(tblForm);
			return;
		}
		
		xtime now = xrtNow();
		
		sqlite3_bind_int64(stmt_user_put, 1, role);
		sqlite3_bind_text(stmt_user_put, 2, user, strlen(user), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_user_put, 3, now);
		sqlite3_bind_int64(stmt_user_put, 4, id);
		sqlite3_step(stmt_user_put);
		sqlite3_reset(stmt_user_put);
		xvoUnref(tblForm);
		
		// 返回成功信息
		http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"用户更新成功！\"}", 0);
		
	} else if ( hm->methodCode == HTTP_DELETE ) {
		
		// 删除用户（软删除）
		// 从URL查询字符串中提取ID
		char sID[24];
		mg_http_get_var(&hm->query, "id", sID, sizeof(sID));
		int64 id = xrtStrToI64(sID);
		if ( id > 0 ) {
			// 执行软删除
			sqlite3_bind_int64(stmt_user_del, 1, id);
			sqlite3_step(stmt_user_del);
			sqlite3_reset(stmt_user_del);
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"用户删除成功！\"}", 0);
		} else {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无效的用户ID\"}", 0);
		}
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// 重置密码接口
void Request_Auth_User_Repwd(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_POST ) {
		
		// 重置密码
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 id = xvoTableGetInt(tblForm, "id", 2);
		str password = xvoTableGetText(tblForm, "password", 8);
		
		if (!password || strlen(password) == 0) {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"密码不能为空！\"}", 0);
			xvoUnref(tblForm);
			return;
		}
		
		// 获取用户名（用于计算 MD5）
		str sSQL = xrtFormat("SELECT user FROM user WHERE id = %lld AND isDelete = 0", id);
		XDO_Recordset rs = xdoSelect(G_DB, sSQL);
		xrtFree(sSQL);
		
		if (xrsGetRecordCount(rs) == 0) {
			xrsFree(rs);
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"用户不存在！\"}", 0);
			xvoUnref(tblForm);
			return;
		}
		
		xrsNext(rs);
		str user = xrsGetValue(rs, 0);
		
		// 计算密码的 MD5 值
		mg_md5_ctx ctx;
		mg_md5_init(&ctx);
		mg_md5_update(&ctx, user, strlen(user));
		mg_md5_update(&ctx, "_xPanel_", 8);
		mg_md5_update(&ctx, password, strlen(password));
		uint8 buf[16];
		mg_md5_final(&ctx, buf);
		str sPwdMD5 = xrtHexEncode(buf, 16);
		
		xrsFree(rs);
		
		xtime now = xrtNow();
		
		// 更新密码
		sqlite3_bind_text(stmt_user_pwd, 1, sPwdMD5, strlen(sPwdMD5), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_user_pwd, 2, now);
		sqlite3_bind_int64(stmt_user_pwd, 3, id);
		sqlite3_step(stmt_user_pwd);
		sqlite3_reset(stmt_user_pwd);
		
		xrtFree(sPwdMD5);
		xvoUnref(tblForm);
		
		// 返回成功信息
		http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"密码重置成功！\"}", 0);
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// role 主接口
void Request_Auth_Role(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 从数据库读取数据
		XDO_Recordset rs = xdoSelect(G_DB, "SELECT * FROM role WHERE isDelete = 0 ORDER BY id ASC;");
		xvalue data = xvoCreateArray();
		while ( xrsNext(rs) ) {
			xvalue tblRow = xvoCreateTable();
			int64 id = xrtStrToI64(xrsGetValue(rs, 0));
			xvoTableSetInt(tblRow, "id", 2, id);
			xvoTableSetText(tblRow, "name", 4, xrsGetValue(rs, 1), 0, FALSE);
			xvoTableSetText(tblRow, "desc", 4, xrsGetValue(rs, 2), 0, FALSE);
			xvoTableSetText(tblRow, "authList", 8, xrsGetValue(rs, 3), 0, FALSE);
			xtime iTime = xrtStrToI64(xrsGetValue(rs, 4));
			xvoTableSetText(tblRow, "createTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			iTime = xrtStrToI64(xrsGetValue(rs, 5));
			xvoTableSetText(tblRow, "updateTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			xvoArrayAppendValue(data, tblRow, TRUE);
		}
		xrsFree(rs);
		// 返回接口数据
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "角色数据获取成功！", 0, FALSE);
		xvoTableSetValue(tblRet, "data", 4, data, TRUE);
		// 生成 JSON
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_POST ) {
		
		// 添加角色
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		str name = xvoTableGetText(tblForm, "name", 4);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		str authList = xvoTableGetText(tblForm, "authList", 8);
		if (!authList || strlen(authList) == 0) {
			authList = "[]";
		}
		xtime now = xrtNow();
		
		sqlite3_bind_text(stmt_role_add, 1, name, strlen(name), SQLITE_STATIC);
		sqlite3_bind_text(stmt_role_add, 2, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_text(stmt_role_add, 3, authList, strlen(authList), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_role_add, 4, now);
		sqlite3_bind_int64(stmt_role_add, 5, now);
		sqlite3_step(stmt_role_add);
		int64 newId = sqlite3_last_insert_rowid(G_DB->objDB);
		sqlite3_reset(stmt_role_add);
		xvoUnref(tblForm);
		
		// 返回成功信息和新创建的ID
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "角色添加成功！", 0, FALSE);
		xvalue dataRet = xvoCreateTable();
		xvoTableSetInt(dataRet, "id", 2, newId);
		xvoTableSetValue(tblRet, "data", 4, dataRet, TRUE);
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_PUT ) {
		
		// 更新角色
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 id = xvoTableGetInt(tblForm, "id", 2);
		str name = xvoTableGetText(tblForm, "name", 4);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		str authList = xvoTableGetText(tblForm, "authList", 8);
		if (!authList || strlen(authList) == 0) {
			authList = "[]";
		}
		xtime now = xrtNow();
		
		sqlite3_bind_text(stmt_role_put, 1, name, strlen(name), SQLITE_STATIC);
		sqlite3_bind_text(stmt_role_put, 2, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_text(stmt_role_put, 3, authList, strlen(authList), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_role_put, 4, now);
		sqlite3_bind_int64(stmt_role_put, 5, id);
		sqlite3_step(stmt_role_put);
		sqlite3_reset(stmt_role_put);
		xvoUnref(tblForm);
		
		// 返回成功信息
		http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"角色更新成功！\"}", 0);
		
	} else if ( hm->methodCode == HTTP_DELETE ) {
		
		// 删除角色（软删除）
		// 从URL查询字符串中提取ID
		char sID[24];
		mg_http_get_var(&hm->query, "id", sID, sizeof(sID));
		int64 id = xrtStrToI64(sID);
		if ( id > 0 ) {
			
			// 检查是否有关联的用户
			char sql[128] = {0};
			sprintf(sql, "SELECT COUNT(*) FROM user WHERE role = %lld AND isDelete = 0", id);
			XDO_Recordset rs = xdoSelect(G_DB, sql);
			int64 count = 0;
			if (xrsNext(rs)) {
				count = xrtStrToI64(xrsGetValue(rs, 0));
			}
			xrsFree(rs);
			
			if (count > 0) {
				// 有关联的用户，不能删除
				http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无法删除此角色，因为它关联了用户！\"}", 0);
			} else {
				// 没有关联的用户，可以删除
				sqlite3_bind_int64(stmt_role_del, 1, id);
				sqlite3_step(stmt_role_del);
				sqlite3_reset(stmt_role_del);
				http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"角色删除成功！\"}", 0);
			}
		} else {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无效的角色ID\"}", 0);
		}
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// group 主接口
void Request_Auth_Group(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 从数据库读取数据
		XDO_Recordset rs = xdoSelect(G_DB, "SELECT * FROM authGroup WHERE isDelete = 0 ORDER BY sort ASC, id ASC;");
		xvalue data = xvoCreateArray();
		while ( xrsNext(rs) ) {
			xvalue tblRow = xvoCreateTable();
			int64 id = xrtStrToI64(xrsGetValue(rs, 0));
			xvoTableSetInt(tblRow, "id", 2, id);
			xvoTableSetText(tblRow, "name", 4, xrsGetValue(rs, 1), 0, FALSE);
			xvoTableSetText(tblRow, "desc", 4, xrsGetValue(rs, 2), 0, FALSE);
			xvoTableSetInt(tblRow, "sort", 4, xrtStrToI64(xrsGetValue(rs, 3)));
			xtime iTime = xrtStrToI64(xrsGetValue(rs, 4));
			xvoTableSetText(tblRow, "createTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			iTime = xrtStrToI64(xrsGetValue(rs, 5));
			xvoTableSetText(tblRow, "updateTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			xvoArrayAppendValue(data, tblRow, TRUE);
		}
		xrsFree(rs);
		// 返回接口数据
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "接口数据获取成功！", 0, FALSE);
		xvoTableSetValue(tblRet, "data", 4, data, TRUE);
		// 生成 JSON
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, "Content-Type: application/json\r\n", sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_POST ) {
		
		// 添加权限大分类
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		str name = xvoTableGetText(tblForm, "name", 4);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		int64 sort = xvoTableGetInt(tblForm, "sort", 4);
		xtime now = xrtNow();
		
		sqlite3_bind_text(stmt_authGroup_add, 1, name, strlen(name), SQLITE_STATIC);
		sqlite3_bind_text(stmt_authGroup_add, 2, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_authGroup_add, 3, sort);
		sqlite3_bind_int64(stmt_authGroup_add, 4, now);
		sqlite3_bind_int64(stmt_authGroup_add, 5, now);
		sqlite3_step(stmt_authGroup_add);
		int64 newId = sqlite3_last_insert_rowid(G_DB->objDB);
		sqlite3_reset(stmt_authGroup_add);
		xvoUnref(tblForm);
		
		// 返回成功信息和新创建的ID
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "权限大分类添加成功！", 0, FALSE);
		xvalue dataRet = xvoCreateTable();
		xvoTableSetInt(dataRet, "id", 2, newId);
		xvoTableSetValue(tblRet, "data", 4, dataRet, TRUE);
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_PUT ) {
		
		// 更新权限大分类
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 id = xvoTableGetInt(tblForm, "id", 2);
		str name = xvoTableGetText(tblForm, "name", 4);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		int64 sort = xvoTableGetInt(tblForm, "sort", 4);
		xtime now = xrtNow();
		
		sqlite3_bind_text(stmt_authGroup_put, 1, name, strlen(name), SQLITE_STATIC);
		sqlite3_bind_text(stmt_authGroup_put, 2, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_authGroup_put, 3, sort);
		sqlite3_bind_int64(stmt_authGroup_put, 4, now);
		sqlite3_bind_int64(stmt_authGroup_put, 5, id);
		sqlite3_step(stmt_authGroup_put);
		sqlite3_reset(stmt_authGroup_put);
		xvoUnref(tblForm);
		
		// 返回成功信息
		http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"权限大分类更新成功！\"}", 0);
		
	} else if ( hm->methodCode == HTTP_DELETE ) {
		
		// 删除权限大分类（软删除）
		// 从URL查询字符串中提取ID
		char sID[24];
		mg_http_get_var(&hm->query, "id", sID, sizeof(sID));
		int64 id = xrtStrToI64(sID);
		if ( id > 0 ) {
			
			// 检查是否有关联的权限组
			char sql[128] = {0};
			sprintf(sql, "SELECT COUNT(*) FROM auth WHERE groupID = %lld AND isDelete = 0", id);
			XDO_Recordset rs = xdoSelect(G_DB, sql);
			int64 count = 0;
			if (xrsNext(rs)) {
				count = xrtStrToI64(xrsGetValue(rs, 0));
			}
			xrsFree(rs);
			
			if (count > 0) {
				// 有关联的权限组，不能删除
				http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无法删除此分类，因为它关联了权限组！\"}", 0);
			} else {
				// 没有关联的权限组，可以删除
				sqlite3_bind_int64(stmt_authGroup_del, 1, id);
				sqlite3_step(stmt_authGroup_del);
				sqlite3_reset(stmt_authGroup_del);
				http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"权限大分类删除成功！\"}", 0);
			}
		} else {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无效的分类ID\"}", 0);
		}
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// auth 主接口
void Request_Auth_Auth(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 从数据库读取数据
		XDO_Recordset rs = xdoSelect(G_DB, "SELECT * FROM auth WHERE isDelete = 0 ORDER BY sort ASC, id ASC;");
		xvalue data = xvoCreateArray();
		while ( xrsNext(rs) ) {
			xvalue tblRow = xvoCreateTable();
			int64 id = xrtStrToI64(xrsGetValue(rs, 0));
			xvoTableSetInt(tblRow, "id", 2, id);
			xvoTableSetInt(tblRow, "groupID", 7, xrtStrToI64(xrsGetValue(rs, 1)));
			xvoTableSetText(tblRow, "name", 4, xrsGetValue(rs, 2), 0, FALSE);
			xvoTableSetText(tblRow, "desc", 4, xrsGetValue(rs, 3), 0, FALSE);
			xvoTableSetInt(tblRow, "sort", 4, xrtStrToI64(xrsGetValue(rs, 4)));
			xtime iTime = xrtStrToI64(xrsGetValue(rs, 5));
			xvoTableSetText(tblRow, "createTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			iTime = xrtStrToI64(xrsGetValue(rs, 6));
			xvoTableSetText(tblRow, "updateTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
			xvoArrayAppendValue(data, tblRow, TRUE);
		}
		xrsFree(rs);
		// 返回接口数据
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "权限数据获取成功！", 0, FALSE);
		xvoTableSetValue(tblRet, "data", 4, data, TRUE);
		// 生成 JSON
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_POST ) {
		
		// 添加权限组
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 groupID = xvoTableGetInt(tblForm, "groupID", 7);
		str name = xvoTableGetText(tblForm, "name", 4);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		int64 sort = xvoTableGetInt(tblForm, "sort", 4);
		xtime now = xrtNow();
		
		sqlite3_bind_int64(stmt_auth_add, 1, groupID);
		sqlite3_bind_text(stmt_auth_add, 2, name, strlen(name), SQLITE_STATIC);
		sqlite3_bind_text(stmt_auth_add, 3, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_auth_add, 4, sort);
		sqlite3_bind_int64(stmt_auth_add, 5, now);
		sqlite3_bind_int64(stmt_auth_add, 6, now);
		sqlite3_step(stmt_auth_add);
		int64 newId = sqlite3_last_insert_rowid(G_DB->objDB);
		sqlite3_reset(stmt_auth_add);
		xvoUnref(tblForm);
		
		// 返回成功信息和新创建的ID
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetText(tblRet, "message", 7, "权限组添加成功！", 0, FALSE);
		xvalue data = xvoCreateTable();
		xvoTableSetInt(data, "id", 2, newId);
		xvoTableSetValue(tblRet, "data", 4, data, TRUE);
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_PUT ) {
		
		// 更新权限组
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 id = xvoTableGetInt(tblForm, "id", 2);
		int64 groupID = xvoTableGetInt(tblForm, "groupID", 7);
		str name = xvoTableGetText(tblForm, "name", 4);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		int64 sort = xvoTableGetInt(tblForm, "sort", 4);
		xtime now = xrtNow();
		
		sqlite3_bind_int64(stmt_auth_put, 1, groupID);
		sqlite3_bind_text(stmt_auth_put, 2, name, strlen(name), SQLITE_STATIC);
		sqlite3_bind_text(stmt_auth_put, 3, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_auth_put, 4, sort);
		sqlite3_bind_int64(stmt_auth_put, 5, now);
		sqlite3_bind_int64(stmt_auth_put, 6, id);
		sqlite3_step(stmt_auth_put);
		sqlite3_reset(stmt_auth_put);
		xvoUnref(tblForm);
		
		// 返回成功信息
		http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"权限组更新成功！\"}", 0);
		
	} else if ( hm->methodCode == HTTP_DELETE ) {
		
		// 删除权限组（软删除）
		// 从URL查询字符串中提取ID
		char sID[24];
		mg_http_get_var(&hm->query, "id", sID, sizeof(sID));
		int64 id = xrtStrToI64(sID);
		if ( id > 0 ) {
			
			// 检查是否有关联的URI权限
			char sql[128] = {0};
			sprintf(sql, "SELECT COUNT(*) FROM uris WHERE authID = %lld AND isDelete = 0", id);
			XDO_Recordset rs = xdoSelect(G_DB, sql);
			int64 count = 0;
			if (xrsNext(rs)) {
				count = xrtStrToI64(xrsGetValue(rs, 0));
			}
			xrsFree(rs);
			
			if (count > 0) {
				// 有关联的URI权限，不能删除
				http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无法删除此权限组，因为它关联了URI权限！\"}", 0);
			} else {
				// 没有关联的URI权限，可以删除
				sqlite3_bind_int64(stmt_auth_del, 1, id);
				sqlite3_step(stmt_auth_del);
				sqlite3_reset(stmt_auth_del);
				http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"message\": \"权限组删除成功！\"}", 0);
			}
		} else {
			http_reply(c, 200, HTTP_CT_JSON, "{\"result\": false, \"message\": \"无效的权限组ID\"}", 0);
		}
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}



// uris 主接口
void Request_Auth_URIs(XS_ServerObject objServer, XS_HostObject objHost, struct mg_connection* c, struct mg_http_message* hm)
{
	if ( hm->methodCode == HTTP_GET ) {
		
		// 从 URL 查询字符串中提取参数
		char sParam[64];
		mg_http_get_var(&hm->query, "page", sParam, sizeof(sParam));
		int64 iPage = xrtStrToI64(sParam);
		if ( iPage <= 0 ) { iPage = 1; }
		mg_http_get_var(&hm->query, "limit", sParam, sizeof(sParam));
		int64 iLimit = xrtStrToI64(sParam);
		if ( iLimit <= 0 ) { iLimit = 10; }
		int64 iOffset = (iPage - 1) * iLimit;
		int iSize = mg_http_get_var(&hm->query, "search", sParam, sizeof(sParam));
		
		// 从数据库中查询数据
		xvalue data = xvoCreateArray();
		int64 iCount = 0;
		if ( iSize <= 0 ) {
			// 查询全部
			sqlite3_bind_int64(stmt_uris_all, 1, iLimit);
			sqlite3_bind_int64(stmt_uris_all, 2, iOffset);
			while ( sqlite3_step(stmt_uris_all) == SQLITE_ROW ) {
				xvalue tblRow = xvoCreateTable();
				xvoTableSetInt(tblRow, "id", 2, sqlite3_column_int64(stmt_uris_all, 0));
				xvoTableSetInt(tblRow, "authID", 6, sqlite3_column_int64(stmt_uris_all, 1));
				xvoTableSetText(tblRow, "uri", 3, (str)sqlite3_column_text(stmt_uris_all, 2), 0, FALSE);
				xvoTableSetText(tblRow, "desc", 4, (str)sqlite3_column_text(stmt_uris_all, 3), 0, FALSE);
				xvoTableSetInt(tblRow, "sort", 4, sqlite3_column_int64(stmt_uris_all, 4));
				xtime iTime = sqlite3_column_int64(stmt_uris_all, 5);
				xvoTableSetText(tblRow, "createTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
				xvoTableSetText(tblRow, "authName", 8, (str)sqlite3_column_text(stmt_uris_all, 6), 0, FALSE);
				if ( iCount <= 0 ) {
					iCount = sqlite3_column_int64(stmt_uris_all, 7);
				}
				xvoArrayAppendValue(data, tblRow, TRUE);
			}
			sqlite3_reset(stmt_uris_all);
		} else {
			// 筛选
			sqlite3_bind_text(stmt_uris_sel, 1, sParam, iSize, NULL);
			sqlite3_bind_text(stmt_uris_sel, 2, sParam, iSize, NULL);
			sqlite3_bind_int64(stmt_uris_sel, 3, iLimit);
			sqlite3_bind_int64(stmt_uris_sel, 4, iOffset);
			while ( sqlite3_step(stmt_uris_sel) == SQLITE_ROW ) {
				xvalue tblRow = xvoCreateTable();
				xvoTableSetInt(tblRow, "id", 2, sqlite3_column_int64(stmt_uris_sel, 0));
				xvoTableSetInt(tblRow, "authID", 6, sqlite3_column_int64(stmt_uris_sel, 1));
				xvoTableSetText(tblRow, "uri", 3, (str)sqlite3_column_text(stmt_uris_sel, 2), 0, FALSE);
				xvoTableSetText(tblRow, "desc", 4, (str)sqlite3_column_text(stmt_uris_sel, 3), 0, FALSE);
				xvoTableSetInt(tblRow, "sort", 4, sqlite3_column_int64(stmt_uris_sel, 4));
				xtime iTime = sqlite3_column_int64(stmt_uris_sel, 5);
				xvoTableSetText(tblRow, "createTime", 10, xrtTimeToStr(iTime, XRT_TIME_FORMAT_DATETIME), 0, TRUE);
				xvoTableSetText(tblRow, "authName", 8, (str)sqlite3_column_text(stmt_uris_sel, 6), 0, FALSE);
				if ( iCount <= 0 ) {
					iCount = sqlite3_column_int64(stmt_uris_sel, 7);
				}
				xvoArrayAppendValue(data, tblRow, TRUE);
			}
			sqlite3_reset(stmt_uris_sel);
		}
		
		// 构建返回值
		xvalue tblRet = xvoCreateTable();
		xvoTableSetBool(tblRet, "result", 6, TRUE);
		xvoTableSetInt(tblRet, "code", 4, 0);
		xvoTableSetInt(tblRet, "count", 5, iCount);
		xvoTableSetText(tblRet, "msg", 3, "接口数据获取成功！", 0, FALSE);
		xvoTableSetValue(tblRet, "data", 4, data, TRUE);
		
		// 生成 JSON
		size_t iRetSize = 0;
		char* sRet = xrtStringifyJSON(tblRet, FALSE, &iRetSize);
		http_reply(c, 200, HTTP_CT_JSON, sRet, iRetSize);
		//xrtFree(sRet);
		xvoUnref(tblRet);
		
	} else if ( hm->methodCode == HTTP_PUT ) {
		
		// 更新接口信息
		xvalue tblForm = xrtParseJSON(hm->body.buf, hm->body.len);
		int64 id = xvoTableGetInt(tblForm, "id", 2);
		int64 authID = xvoTableGetInt(tblForm, "authID", 6);
		str desc = xvoTableGetText(tblForm, "desc", 4);
		int64 sort = xvoTableGetInt(tblForm, "sort", 4);
		sqlite3_bind_int64(stmt_uris_put, 1, authID);
		sqlite3_bind_text(stmt_uris_put, 2, desc, strlen(desc), SQLITE_STATIC);
		sqlite3_bind_int64(stmt_uris_put, 3, sort);
		sqlite3_bind_int64(stmt_uris_put, 4, id);
		sqlite3_step(stmt_uris_put);
		sqlite3_reset(stmt_uris_put);
		xvoUnref(tblForm);
		// 重新加载 URI 表
		//ReloadDB_uris();
		http_reply(c, 200, HTTP_CT_JSON, "{\"result\": true, \"msg\": \"接口信息修改成功！\"}", 0);
		
	} else {
		
		// 其他请求方法返回 404 页面
		LoadPage(c, 404, HTTP_CT_HTML, "status/404.html");
		
	}
}


